package com.honor.games.wg.graphics;

import java.util.Map;
import java.util.HashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.google.common.eventbus.EventBus;
import com.honor.games.wg.config.ApplicationConfiguration;
import com.honor.games.wg.entities.WGBoard;
import com.honor.games.wg.entities.WGCoordinates;
import com.honor.games.wg.entities.WGTile;
import com.honor.games.wg.graphics.actors.WGActorType;
import com.honor.games.wg.graphics.actors.WGBoardActor;
import com.honor.games.wg.graphics.actors.WGBoardClickListener;
import com.honor.games.wg.services.WGGraphicsServices;
import com.honor.games.wg.services.WGMathServices;
import com.honor.games.wg.services.WGWorldServices;

import com.honor.games.wg.entities.WGUnitType;
import com.honor.games.wg.events.TileClickedEvent;

@Service
public class WGGraphics implements ApplicationListener {

	private static Logger logger = LoggerFactory.getLogger(WGGraphics.class);

	@Autowired
	private ApplicationConfiguration config;

	@Autowired
	private WGGraphicsServices graphicsService;

	@Autowired
	private WGMathServices mathServices;

	@Autowired
	private WGWorldServices worldServices;

	@Autowired
	private EventBus eventBus;

	private float delta;
	private float elapsed;

	private WGBoardActor boardActor;
	private Stage stage;

	private Map<WGUnitType, Texture> texturesPerUnitType = new HashMap<WGUnitType, Texture>();
	private Texture unitSelectionTexture;

	private Vector2 initialPosition = new Vector2();

	@Override
	public void create() {
		logger.trace("Creating graphics environment - START");
		logger.trace("Graphical configuration :");
		logger.trace("Resolution : {}, {}", Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

		stage = new Stage();
		Gdx.input.setInputProcessor(stage);

		logger.trace("Viewport set to {}, {}", config.getScreenWidth(), config.getScreenHeight());
		stage.setViewport(config.getScreenWidth(), config.getScreenHeight(), false);

		logger.trace("Loading textures...");
		texturesPerUnitType.put(WGUnitType.ELVE, new Texture(Gdx.files.internal("elve.png")));
		texturesPerUnitType.put(WGUnitType.ORC, new Texture(Gdx.files.internal("orc.png")));
		unitSelectionTexture = new Texture(Gdx.files.internal("unit_selector.png"));

		initialPosition.set((config.getScreenWidth() - config.getBoardTilesSizeWidth() * config.getBoardTilesWidthNumber()) / 2,
				(config.getScreenHeight() - config.getBoardTilesSizeHeight() * config.getBoardTilesHeightNumber()) / 2);
		mathServices.setInitialPosition(initialPosition);

		logger.trace("Creating board actor...");
		WGBoardActor boardActor = new WGBoardActor("board", WGActorType.BOARD, config.getBoardTilesSizeWidth(),
				config.getBoardTilesSizeHeight(), config.getBoardTilesWidthNumber(), config.getBoardTilesHeightNumber(), initialPosition.x,
				initialPosition.y);
		boardActor.addListener(new WGBoardClickListener(boardActor, this));
		stage.addActor(boardActor);
		graphicsService.setBoardActor(boardActor);

		graphicsService.setStage(stage);
		graphicsService.setTextures(texturesPerUnitType, unitSelectionTexture);

		logger.trace("Creating graphics environnement - STOP");
	}

	@Override
	public void resize(int width, int height) {
		logger.trace("Resizing screen : {}, {} - START", width, height);
		logger.trace("Resizing screen - STOP");
	}

	@Override
	public void render() {
		delta = Gdx.graphics.getDeltaTime();
		elapsed += delta;
		Gdx.gl.glClearColor(0, 0, 0, 0);
		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

		stage.act(delta);
		stage.draw();
	}

	@Override
	public void pause() {
		logger.trace("Pausing Graphics - START");
		logger.trace("Pausing Graphics - STOP");
	}

	@Override
	public void resume() {
		logger.trace("Resuming Graphics - START");
		logger.trace("Resuming Graphics - STOP");
	}

	@Override
	public void dispose() {
		logger.trace("Disposing - START");
		logger.trace("Disposing - STOP");
	}
	
	public void handleBoardClick(WGBoardActor boardActor, float x, float y) {
		logger.trace("Handle board click - START");
		logger.trace("Click at {}, {} on board. Calculating tile coordinates.", x, y);
		WGCoordinates coordinates = mathServices.calculateTileCoordinates(x, y, true);
		logger.trace("Tile coordinates : {}, {}", coordinates.getX(), coordinates.getY());
		WGTile clickedTile = worldServices.getTile(coordinates.getX(), coordinates.getY());
		eventBus.post(new TileClickedEvent(clickedTile));
		logger.trace("Handle board click - STOP");
	}	
}
